﻿
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;

using ChangeListLibrary;

namespace CodeReviewApplication.Models.Client
{
    #region types

    [DataContract]
    public partial class CommentThreadsByStatus
    {
        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ulong OpenCount;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ulong ClosedCount;

        public CommentThreadsByStatus()
        {
        }

        public CommentThreadsByStatus(
            IEnumerable<CodeReviewApplication.Models.CommentThread> threads
            )
        {
            OpenCount = (ulong)threads.Where(
                thread => thread.IsInState(CommentThreadStatusEnum.Open)
                ).Count();

            ClosedCount = (ulong)threads.Where(
                thread => thread.IsInState(CommentThreadStatusEnum.Closed)
                ).Count();
        }
    }

    [DataContract]
    public partial class Author
    {
        [DataMember(IsRequired = true)]
        [XmlElement]
        public CommentThreadsByStatus CommentThreadsStatus;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public string Name;

        public Author()
        {
        }

        public Author(
            ReviewUserRole authorRole,
            IEnumerable<CodeReviewApplication.Models.CommentThread> threads
            )
        {
            Name = authorRole.UserId;
            CommentThreadsStatus = new CommentThreadsByStatus(
                threads.Where(thread => thread.IsAuthor(Name))
                );
        }
    }

    [DataContract(Name = "Reviewer")]
    public partial class ReviewReviewer
    {
        [DataMember(IsRequired = true)]
        [XmlElement]
        public CommentThreadsByStatus CommentThreadsStatus;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public string Name;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public UserReviewStatusEnum Status;

        public ReviewReviewer()
        {
        }

        public ReviewReviewer(
            ReviewUserRole userRole,
            IEnumerable<CodeReviewApplication.Models.CommentThread> threads,
            string userId
            )
        {
            Name = userRole.UserId;
            Status = userRole.StatusEnum;
            CommentThreadsStatus = new CommentThreadsByStatus(
                threads.Where(thread => thread.IsAuthor(Name) && thread.IsVisible(userId))
                );
        }

        public static ReviewReviewer[] ToArray(
            CodeReviewApplication.Models.Review review,
            string userId
            )
        {
            return (
                from role in review.ReviewerRoles
                select new ReviewReviewer(role, review.CommentThreads, userId)
                ).ToArray();
        }
    }

    [DataContract]
    public partial class ReviewSummary
    {
        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ulong Id;

        [DataMember(IsRequired = true)]
        [XmlElement]
        public Author Author;

        [DataMember(IsRequired = false)]
        [XmlArrayItem("Reviewer", IsNullable = false)]
        public ReviewReviewer[] Reviewers;

        [DataMember(IsRequired = true)]
        [XmlElement]
        public CommentThreadsByStatus CommentThreadsStatus;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ReviewStatusEnum Status;

        [DataMember(IsRequired = true)]
        [XmlElement]
        public string Title;

        [DataMember(IsRequired = true)]
        [XmlElement]
        public string Description;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public DateTime CreatedOn;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public DateTime ModifiedOn;

        public ReviewSummary()
        {
        }

        public ReviewSummary(
            CodeReviewApplication.Models.Review review,
            string userId
            )
        {
            Author = new Author(review.AuthorRole, review.CommentThreads);
            CommentThreadsStatus = new CommentThreadsByStatus(review.CommentThreads);
            CreatedOn = review.CreatedOn;
            Description = review.Description;
            Id = (ulong)review.Id;
            ModifiedOn = review.ModifiedOn;
            Reviewers = ReviewReviewer.ToArray(review, userId);
            Status = review.StatusEnum;
            Title = review.Title;
        }

        public static ReviewSummary[] ToArray(
            IEnumerable<ReviewView> reviewViews,
            string userId
            )
        {
            return (
                from reviewView in reviewViews
                select new ReviewSummary(reviewView.Review, userId)
                ).ToArray();
        }

        public static ReviewSummary[] ToArray(
            IEnumerable<CodeReviewApplication.Models.Review> reviews,
            string userId
            )
        {
            return (
                from review in reviews
                select new Review(review, userId)
                ).ToArray();
        }

        public bool IsAuthor(
            string author
            )
        {
            return (string.Compare(Author.Name, author, true) == 0);
        }

        public override string ToString()
        {
            return string.Format(
                "{0}: '{1}' by {2}@{3:G}",
                Id,
                Title,
                Author.Name,
                ModifiedOn.ToLocalTime()
                );
        }
    }

    [DataContract]
    public partial class Change
    {
        [DataMember(IsRequired = true)]
        [XmlElement]
        public CommentThreadsByStatus CommentThreadsStatus;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ulong Id;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ulong ChangeListId;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ChangeTypeEnum Type;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public FileTypeEnum FileType;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public string OldName;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public string OldVersion;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public string NewName;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public string NewVersion;

        public Change()
        {
        }

        public Change(ChangeListItem changeListItem)
        {
            ChangeListId = (ulong)changeListItem.ChangeListId;
            CommentThreadsStatus = new CommentThreadsByStatus(changeListItem.CommentThreads);
            FileType = changeListItem.FileTypeEnum;
            Id = (ulong)changeListItem.Id;
            NewName = changeListItem.NewName;
            NewVersion = changeListItem.NewVersion;
            OldName = changeListItem.Name;
            OldVersion = changeListItem.Version;
            Type = changeListItem.TypeEnum;
        }

        public static Change[] ToArray(
            IEnumerable<ChangeListItem> changeListItems
            )
        {
            return (from changeListItem in changeListItems
                    select new Change(changeListItem)).ToArray();
        }
    }

    [DataContract]
    public partial class Review : ReviewSummary
    {
        [DataMember(IsRequired = false)]
        public Change[] Changes;

        public Review()
        {
        }

        public Review(
            CodeReviewApplication.Models.Review review,
            string userId
            ) : base(review, userId)
        {
            Changes = Change.ToArray(review.LatestChangeListItems);
        }

        public new static Review[] ToArray(
            IEnumerable<ReviewView> reviewViews,
            string userId
            )
        {
            return (
                from reviewView in reviewViews
                select new Review(reviewView.Review, userId)
                ).ToArray();
        }

        public new static Review[] ToArray(
            IEnumerable<CodeReviewApplication.Models.Review> reviews,
            string userId
            )
        {
            return (
                from review in reviews
                select new Review(review, userId)
                ).ToArray();
        }
    }

    [DataContract]
    public partial class Comment
    {
        [DataMember]
        [XmlElement]
        public string Description;

        [DataMember]
        [XmlAttribute]
        public ulong Id;

        [DataMember]
        [XmlAttribute]
        public ulong ThreadId;

        [DataMember]
        [XmlAttribute]
        public ulong ChangeId;

        [DataMember]
        [XmlAttribute]
        public ulong ReviewId;

        [DataMember]
        [XmlAttribute]
        public string Author;

        [DataMember]
        [XmlAttribute]
        public CommentStatusEnum Status;

        [DataMember]
        [XmlAttribute]
        public DateTime CreatedOn;

        public Comment()
        {
        }

        public Comment(
            CodeReviewApplication.Models.Comment comment,
            CodeReviewApplication.Models.CommentThread thread
            )
        {
            Author = comment.AuthorId;
            ChangeId = (ulong)thread.ChangeListItemId;
            CreatedOn = comment.CreatedOn;
            Description = comment.Description;
            Id = (ulong)comment.Id;
            ReviewId = (ulong)comment.CommentThread.Review.Id;
            Status = (CommentStatusEnum)comment.Status;
            ThreadId = (ulong)comment.ThreadId;
        }

        public static Comment[] ToArray(
            IEnumerable<CodeReviewApplication.Models.Comment> comments,
            CodeReviewApplication.Models.CommentThread thread
            )
        {
            return (
                from comment in comments
                select new Comment(comment, thread)
                ).ToArray();
        }
    }

    [DataContract]
    public partial class ChangeListAssociation
    {
        [DataMember(IsRequired = false)]
        [XmlAttribute]
        public ulong Id;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ulong ChangeId;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ulong ChangeListId;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ulong StartLineNumber;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ulong EndLineNumber;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ulong OldStartLineNumber;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ulong OldEndLineNumber;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ulong NewStartLineNumber;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ulong NewEndLineNumber;

        public ChangeListAssociation()
        {
        }

        public ChangeListAssociation(
            CodeReviewApplication.Models.CommentThread thread
            )
        {
            ChangeId = (ulong)thread.ChangeListItemId;
            ChangeListId = (ulong)thread.ChangeListItem.ChangeListId;
            EndLineNumber = (ulong)thread.EndLineNumber;
            Id = (ulong)thread.Id;
            NewEndLineNumber = (ulong)thread.NewEndLineNumber;
            NewStartLineNumber = (ulong)thread.NewStartLineNumber;
            OldEndLineNumber = (ulong)thread.OldEndLineNumber;
            OldStartLineNumber = (ulong)thread.OldStartLineNumber;
            StartLineNumber = (ulong)thread.StartLineNumber;
        }
    }

    [DataContract]
    public partial class CreateChangeListAssociation
    {
        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ulong ChangeId;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ulong StartLineNumber;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ulong EndLineNumber;
    }

    [DataContract]
    public partial class CommentThreadSummary
    {
        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ulong Id;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ulong ChangeId;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ulong ChangeListId;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ulong ReviewId;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public string Author;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public System.DateTime CreatedOn;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public System.DateTime ModifiedOn;

        [DataMember(IsRequired = true)]
        [XmlElement]
        public CommentThreadStatusEnum Status;

        [DataMember(IsRequired = true)]
        [XmlElement]
        public ChangeListAssociation ChangeListAssociation;

        public CommentThreadSummary()
        {
        }

        public CommentThreadSummary(
            CodeReviewApplication.Models.CommentThread thread
            )
        {
            Author = thread.AuthorId;
            ChangeId = (ulong)thread.ChangeListItemId;
            ChangeListAssociation = new ChangeListAssociation(thread);
            ChangeListId = (ulong)thread.ChangeListItem.ChangeListId;
            CreatedOn = thread.CreatedOn;
            Id = (ulong)thread.Id;
            ModifiedOn = thread.ModifiedOn;
            ReviewId = (ulong)thread.Review.Id;
            Status = thread.StatusEnum;
        }

        public static CommentThreadSummary[] ToArray(
            IEnumerable<CodeReviewApplication.Models.CommentThread> threads
            )
        {
            return (
                from thread in threads
                select new CommentThreadSummary(thread)
                ).ToArray();
        }
    }

    [DataContract]
    public partial class CommentThread : CommentThreadSummary
    {
        [DataMember(IsRequired = true)]
        public Comment[] Comments;

        public CommentThread()
        {
        }

        public CommentThread(
            CodeReviewApplication.Models.CommentThread thread
            ) : base(thread)
        {
            Comments = Comment.ToArray(
                thread.Comments,
                thread
                );
        }

        public new static CommentThread[] ToArray(
            IEnumerable<CodeReviewApplication.Models.CommentThread> threads
            )
        {
            return (
                from thread in threads
                select new CommentThread(thread)
                ).ToArray();
        }
    }

    [DataContract]
    public partial class ChangeListSummary
    {
        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ulong Id;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ulong ReviewId;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public string IdInDepot;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public string DepotName;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public string Author;

        [DataMember(IsRequired = true)]
        [XmlElement]
        public string Description;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public DateTime CreatedOn;

        [DataMember(IsRequired = true)]
        [XmlElement]
        public CommentThreadsByStatus CommentThreadsStatus;

        public ChangeListSummary()
        {
        }

        public ChangeListSummary(
            CodeReviewApplication.Models.ChangeList changeList
            )
        {
            Author = changeList.AuthorId;
            CommentThreadsStatus = new CommentThreadsByStatus(changeList.CommentThreads);
            CreatedOn = changeList.CreatedOn;
            DepotName = changeList.DepotName;
            Description = changeList.Description;
            Id = (ulong)changeList.Id;
            IdInDepot = changeList.DepotId;
            ReviewId = (ulong)changeList.ReviewId;
        }

        public static ChangeListSummary[] ToArray(
            IEnumerable<CodeReviewApplication.Models.ChangeList> changeLists
            )
        {
            return (
                from changeList in changeLists
                select new ChangeListSummary(changeList)
                ).ToArray();
        }
    }

    [DataContract]
    public partial class ChangeList : ChangeListSummary
    {
        [DataMember(IsRequired = true)]
        public Change[] Changes;

        public ChangeList()
        {
        }

        public ChangeList(
            CodeReviewApplication.Models.ChangeList changeList
            )
            : base(changeList)
        {
            Changes = Change.ToArray(changeList.ChangeListItems);
        }

        public new static ChangeList[] ToArray(
            IEnumerable<CodeReviewApplication.Models.ChangeList> changeLists
            )
        {
            return (
                from changeList in changeLists
                select new ChangeList(changeList)
                ).ToArray();
        }
    }

    public enum ErrorTypeEnum
    {
        Information,
        Warning,
        Error,
    }

    [DataContract]
    public partial class ErrorDetail
    {
        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ErrorTypeEnum Type;

        [DataMember(IsRequired = true)]
        [XmlElement]
        public string Message;

        public ErrorDetail()
        {
        }

        public ErrorDetail(ErrorTypeEnum type, string message)
        {
            Type = type;
            Message = message;
        }

        public ErrorDetail(string message) : 
            this(ErrorTypeEnum.Error, message)
        {
        }

        public override string ToString()
        {
            return string.Format("{0}:{1}", Type, Message);
        }
    }

    public enum ResponseTypeEnum
    {
        Success,
        Error,
    }

    [DataContract]
    public abstract partial class Response
    {
        [DataMember(IsRequired = false)]
        public ErrorDetail[] ErrorDetails;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ResponseTypeEnum Type;

        public Response()
        {
            Type = ResponseTypeEnum.Success;
        }

        public Response(ResponseTypeEnum type)
        {
            Type = type;
        }

        public Response(Exception exception)
        {
            Trace.TraceError(exception.ToString());

            Type = ResponseTypeEnum.Error;

            List<ErrorDetail> errorDetails = new List<ErrorDetail>();

            errorDetails.Add(new ErrorDetail(exception.Message));

            ErrorDetails = errorDetails.ToArray();
        }

        public Response(
            ModelStateDictionary modelState
            )
        {
            if (!modelState.IsValid)
            {
                Type = ResponseTypeEnum.Error;

                List<ErrorDetail> errorDetails = new List<ErrorDetail>();

                foreach (var state in modelState)
                {
                    foreach (ModelError error in state.Value.Errors)
                    {
                        if (state.Key.Length > 0)
                        {
                            errorDetails.Add(
                                new ErrorDetail(string.Format("{0}: {1}", state.Key, error.ErrorMessage))
                                );
                        }
                        else
                        {
                            errorDetails.Add(new ErrorDetail(error.ErrorMessage));
                        }
                    }
                }

                ErrorDetails = errorDetails.ToArray();
            }
            else
            {
                Type = ResponseTypeEnum.Success;
            }
        }

        public void ThrowOnError()
        {
            if (Type == ResponseTypeEnum.Error)
            {
                StringBuilder builder = new StringBuilder();

                IEnumerable<ErrorDetail> errors = ErrorDetails.Where(
                    item => (item.Type == ErrorTypeEnum.Error)
                    );

                if (errors.Any())
                {
                    foreach (ErrorDetail errorDetail in errors)
                    {
                        builder.AppendLine(errorDetail.ToString());
                    }
                }
                else
                {
                    builder.AppendLine("Failed");
                }

                throw new Exception(builder.ToString());
            }
        }
    }

    [DataContract]
    public partial class Reviewer
    {
        [DataMember]
        [XmlAttribute]
        public string Name;

        [DataMember]
        [XmlAttribute]
        public UserReviewStatusEnum Status
        {
            get
            {
                return m_status;
            }

            set
            {
                m_status = value;
                m_statusSpecified = true;
            }
        }

        public bool StatusSpecified
        {
            get
            {
                return m_statusSpecified;
            }

            set
            {
                m_statusSpecified = value;
            }
        }

        private bool m_fixedUp = false;
        private bool m_statusSpecified = false;
        private UserReviewStatusEnum m_status = UserReviewStatusEnum.NotApplicable;

        private void Fixup()
        {
            if (!m_fixedUp)
            {
                Name = (Name != null) ? Name.Trim() : string.Empty;

                m_fixedUp = true;
            }
        }

        public bool IsEmpty()
        {
            Fixup();

            return (string.IsNullOrEmpty(Name) && !StatusSpecified);
        }

        public bool IsValid()
        {
            Fixup();

            return !string.IsNullOrEmpty(Name);
        }

        public override string ToString()
        {
            Fixup();

            return string.Format("{0}:{1}", Name, Status);
        }

        public Reviewer()
        {
        }

        public Reviewer(string name)
        {
            Name = name;
        }

        public Reviewer(string name, UserReviewStatusEnum status) :
            this(name)
        {
            Status = status;
        }

        public static ReviewerComparer Comparer = new ReviewerComparer();
    }

    public class ReviewerComparer : IEqualityComparer<Reviewer>
    {
        #region IEqualityComparer<Reviewer> Members

        public bool Equals(Reviewer x, Reviewer y)
        {
            return (
                string.Compare(
                    x.ToString(),
                    y.ToString(),
                    StringComparison.InvariantCultureIgnoreCase
                    ) == 0
                );                        
        }

        public int GetHashCode(Reviewer obj)
        {
            return obj.ToString().ToLowerInvariant().GetHashCode();
        }

        #endregion
    }

    [DataContract]
    public partial class ReviewChangeListPackage
    {
        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public string ClientFileName;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public string UploadedFileName;

        private bool m_fixedUp = false;

        private void Fixup()        
        {
            if (!m_fixedUp)
            {
                ClientFileName = (ClientFileName != null) ? ClientFileName.Trim() : string.Empty;
                UploadedFileName = (UploadedFileName != null) ? UploadedFileName.Trim() : string.Empty;

                m_fixedUp = true;
            }
        }

        public bool IsEmpty()
        {
            Fixup();

            return (
                string.IsNullOrEmpty(ClientFileName) &&
                string.IsNullOrEmpty(UploadedFileName)
                );
        }

        public bool IsValid()
        {
            Fixup();

            return (
                !string.IsNullOrEmpty(ClientFileName) &&
                !string.IsNullOrEmpty(UploadedFileName)
                );
        }

        public override string ToString()
        {
            Fixup();

            return string.Format("{0}:{1}", ClientFileName, UploadedFileName);
        }

        public static ReviewChangeListPackageComparer Comparer = new ReviewChangeListPackageComparer();

        public ReviewChangeListPackage()
        {
        }

        public ReviewChangeListPackage(
            string clientFileName,
            string uploadedFileName
            )
        {
            ClientFileName = clientFileName;
            UploadedFileName = Path.GetFileName(uploadedFileName);
            Fixup();
        }
    }

    public class ReviewChangeListPackageComparer : IEqualityComparer<ReviewChangeListPackage>
    {
        #region IEqualityComparer<ReviewChangeListPackage> Members

        public bool Equals(ReviewChangeListPackage x, ReviewChangeListPackage y)
        {
            return (
                string.Compare(
                    x.ToString(),
                    y.ToString(),
                    StringComparison.InvariantCultureIgnoreCase
                    ) == 0
                );
        }

        public int GetHashCode(ReviewChangeListPackage obj)
        {
            return obj.ToString().ToLowerInvariant().GetHashCode();
        }

        #endregion
    }

    [DataContract]
    public partial class ReviewDepotChangeList
    {
        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public string DepotName;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public string ChangeListId;

        private bool m_fixedUp = false;

        private void Fixup()
        {
            if (!m_fixedUp)
            {
                DepotName = (DepotName != null) ? DepotName.Trim() : string.Empty;
                ChangeListId = (ChangeListId != null) ? ChangeListId.Trim() : string.Empty;
                
                m_fixedUp = true;
            }
        }

        public override string ToString()
        {
            Fixup();

            return string.Format("{0}:{1}", DepotName, ChangeListId);
        }

        public bool IsValid(
            SourceControlManager manager
            )
        {
            Fixup();

            return (
                !string.IsNullOrEmpty(DepotName) &&
                !string.IsNullOrEmpty(ChangeListId) &&
                manager.GetAllDepots().Contains(DepotName)
                );
        }

        public bool IsEmpty()
        {
            Fixup();

            return (
                string.IsNullOrEmpty(DepotName) &&
                string.IsNullOrEmpty(ChangeListId)
                );
        }

        public static ReviewDepotChangeListComparer Comparer = new ReviewDepotChangeListComparer();
    }

    public class ReviewDepotChangeListComparer : IEqualityComparer<ReviewDepotChangeList>
    {
        #region IEqualityComparer<ReviewDepotChangeList> Members

        public bool Equals(ReviewDepotChangeList x, ReviewDepotChangeList y)
        {
            return (
                string.Compare(
                    x.ToString(),
                    y.ToString(),
                    StringComparison.InvariantCultureIgnoreCase
                    ) == 0
                );
        }

        public int GetHashCode(ReviewDepotChangeList obj)
        {
            return obj.ToString().ToLowerInvariant().GetHashCode();
        }

        #endregion
    }

    [DataContract]
    public partial class Setting
    {
        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public string Name;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public string Value;

        public Setting()
        {
        }

        public Setting(string name, string value)
        {
            Name = name;
            Value = value;
        }
    };

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class Depot
    {
        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public string Name;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public string Type;

        [DataMember(IsRequired = true)]
        [XmlElement]
        public Setting[] Settings;

        [DataMember(IsRequired = false)]
        [XmlAttribute]
        public string Owner;

        [DataMember(IsRequired = false)]
        [XmlAttribute]
        public bool Edit;

        public Depot()
        {
        }

        public Depot(UserDepot depot)
        {
            Name = depot.Name;
            Owner = depot.Owner;
            Type = depot.Type;
            Settings = Convert(depot.Settings).ToArray();
        }

        public static Depot[] ToArray(
            IEnumerable<UserDepot> depots
            )
        {
            return (
                from depot in depots
                select new Depot(depot)
                ).ToArray();
        }

        public static IEnumerable<Setting> Convert(
            string settings
            )
        {
            return (
                from attribute in XElement.Parse(settings).Attributes()
                select new Setting(attribute.Name.LocalName, attribute.Value)
                );
        }

        public static string Convert(
            IEnumerable<Setting> settings
            )
        {
            XElement element = new XElement(XName.Get("Settings"));

            element.Add(
                (
                    from setting in settings
                    select new XAttribute(XName.Get(setting.Name), setting.Value)
                ).ToArray()
                );

            return element.ToString();
        }

        public static IEnumerable<string> ToDepotNames(
            IEnumerable<Depot> depots
            )
        {
            return (
                from depot in depots
                where !string.IsNullOrEmpty(depot.Name)
                select depot.Name
                );
        }

        public static bool Validate(
            IEnumerable<Depot> depots,
            ModelStateDictionary modelState,
            string userId
            )
        {
            if (!depots.Any())
            {
                modelState.AddModelError(
                    string.Empty,
                    "Missing depot(s) information"
                    );
            }
            else
            {
                foreach (Depot depot in depots)
                {
                    depot.Validate(modelState, userId);
                }
            }

            return modelState.IsValid;
        }

        public static bool ValidateDepotsPresent(
            IEnumerable<string> depotNames,
            ModelStateDictionary modelState,
            SourceControlManager manager,
            string userId
            )
        {
            IEnumerable<string> existingDepots = manager.GetAllDepots();

            foreach (string depotName in depotNames)
            {
                if (!existingDepots.Contains(depotName))
                {
                    modelState.AddModelError(
                        "Depots",
                        string.Format("Depot '{0}' not present", depotName)
                        );
                }
            }

            return modelState.IsValid;
        }

        public static bool ValidateDepotsAbsent(
            IEnumerable<string> depotNames,
            ModelStateDictionary modelState,
            SourceControlManager manager,
            string userId
            )
        {
            IEnumerable<string> existingDepots = manager.GetAllDepots();

            foreach (string depotName in depotNames)
            {
                if (existingDepots.Contains(depotName))
                {
                    modelState.AddModelError(
                        "Depots",
                        string.Format("Depot '{0}' already present", depotName)
                        );
                }
            }

            return modelState.IsValid;
        }

        public static bool Validate(
            IEnumerable<Depot> depots,
            ModelStateDictionary modelState,
            SourceControlManager manager,
            string userId
            )
        {
            Validate(depots, modelState, userId);
            
            ValidateDepotsPresent(
                ToDepotNames(depots),
                modelState,
                manager,
                userId
                );

            return modelState.IsValid;
        }

        public bool Validate(
            ModelStateDictionary modelState,
            string userId
            )
        {
            if (string.IsNullOrEmpty(Name))
            {
                modelState.AddModelError(
                    "Name",
                    "Name cannot be empty"
                    );
            }

            if (string.IsNullOrEmpty(Type))
            {
                modelState.AddModelError(
                    "Type",
                    "Type cannot be empty"
                    );
            }

            if (!Settings.Any())
            {
                modelState.AddModelError(
                    "Settings",
                    "Settings cannot be empty"
                    );
            }

            if (
                !string.IsNullOrEmpty(Owner) &&
                !string.IsNullOrEmpty(userId) &&
                (string.Compare(Owner, userId, true) != 0)
                )
            {
                modelState.AddModelError(
                    "Owner",
                    "Invalid owner name"
                    );
            }

            return modelState.IsValid;
        }

        public bool Validate(
            ModelStateDictionary modelState,
            SourceControlManager manager,
            string userId,
            bool present
            )
        {
            Validate(modelState, userId);

            List<string> depotNames = new List<string>();

            depotNames.Add(Name);

            if (present)
            {
                ValidateDepotsPresent(
                    depotNames,
                    modelState,
                    manager,
                    userId
                    );
            }
            else
            {
                ValidateDepotsAbsent(
                    depotNames,
                    modelState,
                    manager,
                    userId
                    );
            }

            return modelState.IsValid;
        }

        public bool Validate(
            string depotName,
            ModelStateDictionary modelState,
            SourceControlManager manager,
            string userId,
            bool present
            )
        {
            if (string.Compare(depotName, Name, true) != 0)
            {
                modelState.AddModelError(
                    "Name",
                    string.Format(
                        "Invalid '{0}' name for depot",
                        Name
                        )
                    );
            }

            Validate(
                modelState,
                manager,
                userId,
                present
                );

            return modelState.IsValid;
        }
    }

    [DataContract]
    public partial class DepotChangeList
    {
        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public string Id;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public string Author;

        [DataMember(IsRequired = true)]
        [XmlElement]
        public string Description;

        [DataMember(IsRequired = true)]
        [XmlElement]
        public DateTime CreatedOn;

        public DepotChangeList()
        {
        }

        public DepotChangeList(ChangeListDetails changeList)
        {
            Id = changeList.Id;
            Author = changeList.Author;
            Description = changeList.Description;
            CreatedOn = changeList.CreatedOn;
        }

        public static DepotChangeList[] ToArray(
            IEnumerable<ChangeListDetails> changeLists
            )
        {
            return (
                from changeList in changeLists
                select new DepotChangeList(changeList)
                ).ToArray();
        }
    }

    [Flags]
    public enum EditReviewTypeEnum
    {
        EditReviewStatus = 0x01,
        EditReviewerStatus = 0x02,
        EditReviewers = 0x04,
        EditChangeLists = 0x08,
        EditTitle = 0x10,
        EditDescription = 0x20,
        EditAll = 0xFF,
    }

    [DataContract]
    public partial class NewRegistration
    {
        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public string Email { get; set; }

        [DataMember(IsRequired = false)]
        [XmlAttribute]
        public string Comment { get; set; }

        public NewRegistration()
        {
            Email = string.Empty;
            Comment = string.Empty;
        }

        public bool Validate(
            ModelStateDictionary modelState
            )
        {
            if (!EmailValidator.Validate(Email))
            {
                modelState.AddModelError(
                    "Email",
                    "Invalid email address"
                    );
            }

            return modelState.IsValid;
        }
    }

    [DataContract]
    public partial class Registration : NewRegistration
    {
        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public Guid Id;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public RegistrationRequestStatusEnum Status;

        public Registration() : base()
        {
            Status = RegistrationRequestStatusEnum.NotProcessed;
            Id = Guid.Empty;
        }

        public Registration(
            RegistrationRequest request
            )
        {
            Id = request.Id;
            Email = request.Email;
            Comment = request.Comment;
            Status = request.StatusEnum;
        }

        public static Registration[] ToArray(
            IEnumerable<RegistrationRequest> requests
            )
        {
            return (
                from request in requests select new Registration(request)
                ).ToArray();
        }
    }

    [DataContract]
    public partial class RegistrationStatus
    {
        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public Guid Id;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public RegistrationRequestStatusEnum Status;

        public RegistrationStatus()
        {
            Status = RegistrationRequestStatusEnum.NotProcessed;
            Id = Guid.Empty;
        }

        public RegistrationStatus(
            RegistrationRequest request
            )
        {
            Id = request.Id;
            Status = request.StatusEnum;
        }

        public static RegistrationStatus[] ToArray(
            IEnumerable<RegistrationRequest> requests
            )
        {
            return (
                from request in requests select new RegistrationStatus(request)
                ).ToArray();
        }
    }

    #endregion

    #region requests

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class EditReview
    {
        private bool m_statusSpecified = false;
        private ReviewStatusEnum m_status = ReviewStatusEnum.NotStarted;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public EditReviewTypeEnum Type;

        [XmlAttribute]
        [DataMember(IsRequired = true)]
        public ulong Id;

        [DataMember]
        [XmlAttribute]
        public ReviewStatusEnum Status
        {
            get
            {
                return m_status;
            }

            set
            {
                m_status = value;
                m_statusSpecified = true;
            }
        }

        public bool StatusSpecified
        {
            get
            {
                return m_statusSpecified;
            }

            set
            {
                m_statusSpecified = value;
            }
        }

        [DataMember(IsRequired = false)]
        [XmlElement]
        public Reviewer[] Reviewers;

        [DataMember(IsRequired = false)]
        [XmlElement]
        public string Title;

        [DataMember(IsRequired = false)]
        [XmlElement]
        public string Description;

        [DataMember(IsRequired = false)]
        public ReviewDepotChangeList[] ReviewDepotChangeLists;

        [DataMember(IsRequired = false)]
        public ReviewChangeListPackage[] ReviewChangeListPackages;
        
        public EditReview()
        {
        }

        public EditReview(EditReviewTypeEnum type, ulong reviewId)
        {
            Type = type;
            Id = reviewId;
        }

        public EditReview(EditReviewTypeEnum type, long reviewId) :
            this(type, (ulong)reviewId)
        {
        }

        public EditReview(EditReviewTypeEnum type, int reviewId) : 
            this(type, (ulong)reviewId)
        {
        }

        public EditReview(EditReviewTypeEnum type, long reviewId, Reviewer reviewer) :
            this(type, reviewId)
        {
            Reviewers = new Reviewer[1];
            Reviewers[0] = reviewer;
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class EditReviews
    {
        [DataMember(IsRequired = true)]
        public EditReview[] Reviews;
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class EditCommentThread
    {
        private bool m_statusSpecified = false;
        private CommentThreadStatusEnum m_status = CommentThreadStatusEnum.Open;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ulong Id;

        [DataMember(IsRequired = false)]
        [XmlAttribute]
        public CommentThreadStatusEnum Status
        {
            get
            {
                return m_status;
            }

            set
            {
                m_status = value;
                m_statusSpecified = true;
            }
        }

        public bool StatusSpecified
        {
            get
            {
                return m_statusSpecified;
            }

            set
            {
                m_statusSpecified = value;
            }
        }

        [DataMember(IsRequired = false)]
        [XmlElement]
        public ChangeListAssociation ChangeListAssociation;        
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class EditCommentThreads
    {
        [DataMember(IsRequired = true)]
        public EditCommentThread[] CommentThreads;
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class CreateReview
    {
        [DataMember(IsRequired = true)]
        [XmlElement]
        public string Title;
        
        [DataMember]
        [XmlElement]
        public string Description;

        [DataMember(IsRequired = false)]
        [XmlElement]
        public Reviewer[] Reviewers;

        [DataMember(IsRequired = false)]
        [XmlElement]
        public ReviewDepotChangeList[] ReviewDepotChangeLists;

        [DataMember(IsRequired = false)]
        [XmlElement]
        public ReviewChangeListPackage[] ReviewChangeListPackages;

        private bool m_fixedUp = false;

        private void Fixup()
        {
            if (!m_fixedUp)
            {
                Title = (Title != null) ? Title.Trim() : string.Empty;
                Description = (Description != null) ? Description.Trim() : string.Empty;

                if (Reviewers != null)
                {
                    if (Reviewers.Length > 0)
                    {
                        Reviewers = (
                            from reviewer in Reviewers
                            where !reviewer.IsEmpty()
                            select reviewer
                            ).Distinct(Reviewer.Comparer).ToArray();
                    }
                }
                else
                {
                    Reviewers = new Reviewer[0];
                }

                if (ReviewDepotChangeLists != null)
                {
                    if (ReviewDepotChangeLists.Length > 0)
                    {
                        ReviewDepotChangeLists = (
                            from reviewDepotChangeList in ReviewDepotChangeLists
                            where !reviewDepotChangeList.IsEmpty()
                            select reviewDepotChangeList
                            ).Distinct(ReviewDepotChangeList.Comparer).ToArray();
                    }
                }
                else
                {
                    ReviewDepotChangeLists = new ReviewDepotChangeList[0];
                }

                if (ReviewChangeListPackages != null)
                {
                    if (ReviewChangeListPackages.Length > 0)
                    {
                        ReviewChangeListPackages = (
                            from reviewChangeListPackage in ReviewChangeListPackages
                            where !reviewChangeListPackage.IsEmpty()
                            select reviewChangeListPackage
                            ).Distinct(ReviewChangeListPackage.Comparer).ToArray();
                    }
                }
                else
                {
                    ReviewChangeListPackages = new ReviewChangeListPackage[0];
                }

                m_fixedUp = true;
            }
        }

        public bool Validate(
            ModelStateDictionary modelState,
            SourceControlManager manager
            )
        {
            Fixup();

            foreach (Reviewer reviewer in Reviewers)
            {
                MembershipUser user = null;

                try
                {
                    user = Membership.GetUser(reviewer.Name);
                }
                catch (Exception)
                {
                }

                if (user == null)
                {
                    modelState.AddModelError(
                        "Reviewers",
                        string.Format("Invalid reviewer '{0}'", reviewer.Name)
                        );
                }
            }

            IEnumerable<ReviewDepotChangeList> invalidDepotChangeLists =
                    from reviewDepotChangeList in ReviewDepotChangeLists
                    where (!reviewDepotChangeList.IsValid(manager))
                    select reviewDepotChangeList;

            foreach (ReviewDepotChangeList changeList in invalidDepotChangeLists)
            {
                modelState.AddModelError(
                    "ChangeListIds",
                    string.Format("Invalid changelist id '{0}'", changeList.ToString())
                    );
            }

            IEnumerable<ReviewChangeListPackage> invalidChangeListPackages =
                      from reviewChangeListPackage in ReviewChangeListPackages
                      where (!reviewChangeListPackage.IsValid())
                      select reviewChangeListPackage;

            foreach (ReviewChangeListPackage changeList in invalidChangeListPackages)
            {
                modelState.AddModelError(
                    "ChangeListIds",
                    string.Format("Invalid changelist id '{0}'", changeList.ToString())
                    );
            }

            if (
                string.IsNullOrEmpty(Title) &&
                (ReviewDepotChangeLists.Length == 0) &&
                (ReviewChangeListPackages.Length == 0)
                )
            {
                modelState.AddModelError(
                    "",
                    string.Format("'Title' and 'Changelists' both cannot be empty")
                    );
            }

            return modelState.IsValid;
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class CreateComment
    {
        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public ulong ThreadId;

        [DataMember(IsRequired = true)]
        [XmlElement]
        public string Description;
    }

    public enum DiffViewType
    {
        Merged = 4,
        SideBySide = 5
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class CreateCommentThread
    {
        private DiffViewType m_diffViewType = DiffViewType.Merged;
        private bool m_diffViewTypeSpecified = false;

        [DataMember(IsRequired = true)]
        [XmlElement]
        public string Description;

        [DataMember(IsRequired = false)]
        [XmlAttribute]
        public DiffViewType DiffViewType
        {
            get
            {
                return m_diffViewType;
            }

            set
            {
                m_diffViewType = value;
                m_diffViewTypeSpecified = true;
            }
        }

        public bool DiffViewTypeSpecified
        {
            get
            {
                return m_diffViewTypeSpecified;
            }

            set
            {
                m_diffViewTypeSpecified = value;
            }
        }

        [DataMember(IsRequired = true)]
        [XmlElement]
        public CreateChangeListAssociation ChangeListAssociation;
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class CreateDepots
    {
        [DataMember(IsRequired = true)]
        [XmlElement]
        public Depot[] Depots;

        public bool Validate(
            ModelStateDictionary modelState,
            SourceControlManager manager,
            string userId
            )
        {
            Depot.Validate(
                Depots,
                modelState,
                userId
                );

            Depot.ValidateDepotsAbsent(
                Depot.ToDepotNames(Depots),
                modelState,
                manager,
                userId
                );

            return modelState.IsValid;
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class EditDepots
    {
        [DataMember(IsRequired = true)]
        [XmlElement]
        public Depot[] Depots;

        public bool Validate(
            ModelStateDictionary modelState,
            SourceControlManager manager,
            string userId
            )
        {
            return Depot.Validate(
                Depots,
                modelState,
                manager,
                userId
                );
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class DeleteDepots
    {
        [DataMember(IsRequired = true)]
        [XmlElement]
        public string[] DepotNames;

        public bool Validate(
            ModelStateDictionary modelState,
            SourceControlManager manager,
            string userId
            )
        {
            if (!DepotNames.Any())
            {
                modelState.AddModelError(
                    "Depots",
                    "Missing depot names"
                    );
            }
            else
            {
                Depot.ValidateDepotsPresent(
                    DepotNames,
                    modelState,
                    manager,
                    userId
                    );
            }

            return modelState.IsValid;
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class EditRegistrations
    {
        [DataMember(IsRequired = true)]
        [XmlElement]
        public RegistrationStatus[] Registrations;

        public bool Validate(
            ModelStateDictionary modelState,
            ICodeReviewRepository repository
            )
        {
            if (!Registrations.Any())
            {
                modelState.AddModelError(
                    "Registration",
                    "No registration specified to edit"
                    );
            }
            else
            {
                foreach (RegistrationStatus status in Registrations)
                {
                    try
                    {
                        repository.GetRegistrationRequest(status.Id);
                    }
                    catch (Exception)
                    {
                        modelState.AddModelError(
                            "Registration",
                            string.Format("Registration '{0}' not found", status.Id)
                            );
                    }
                }
            }

            return modelState.IsValid;
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class DeleteRegistrations
    {
        [DataMember(IsRequired = true)]
        [XmlElement]
        public Guid[] Ids;

        public bool Validate(
            ModelStateDictionary modelState,
            ICodeReviewRepository repository
            )
        {
            if (!Ids.Any())
            {
                modelState.AddModelError(
                    "Registration",
                    "No registration specified to delete"
                    );
            }
            else
            {
                foreach (Guid id in Ids)
                {
                    try
                    {
                        repository.GetRegistrationRequest(id);
                    }
                    catch (Exception)
                    {
                        modelState.AddModelError(
                            "Registration",
                            string.Format("Registration '{0}' not found", id)
                            );
                    }
                }
            }

            return modelState.IsValid;
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class UserNotification
    {
        [DataMember(IsRequired = true)]
        [XmlElement]
        public String Message;

        public bool Validate(
            ModelStateDictionary modelState
            )
        {
            if (string.IsNullOrEmpty(Message))
            {
                modelState.AddModelError(
                    "Message",
                    "Message cannot be empty"
                    );
            }

            return modelState.IsValid;
        }

        public UserNotification(string message)
        {
            if (message == null)
            {
                message = string.Empty;
            }

            Message = message;
        }

        public UserNotification() : this(string.Empty)
        {
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class UserFeedback
    {
        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public String Name;

        [DataMember(IsRequired = true)]
        [XmlAttribute]
        public String Email;

        [DataMember(IsRequired = true)]
        [XmlElement]
        public String Message;

        public UserFeedback()
        {
            MembershipUser user = Membership.GetUser();

            if (user != null)
            {
                Name = user.UserName;
                Email = user.Email;
            }
            else
            {
                Name = string.Empty;
                Email = string.Empty;
            }

            Message = string.Empty;
        }

        public UserFeedback(string message) : this()
        {
            Message = message;
        }

        public bool Validate(
            ModelStateDictionary modelState
            )
        {
            if (string.IsNullOrEmpty(Name))
            {
                modelState.AddModelError(
                    "Name",
                    "Name cannot be empty"
                    );
            }

            if (!EmailValidator.Validate(Email))
            {
                modelState.AddModelError(
                    "Email",
                    "Email should be valid"
                    );
            }

            if (string.IsNullOrEmpty(Message))
            {
                modelState.AddModelError(
                    "Message",
                    "Message cannot be empty"
                    );
            }

            return modelState.IsValid;
        }
    }

    #endregion

    #region responses

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class CommentResponse : Response
    {
        [DataMember]
        [XmlElement]
        public Comment Comment;

        public CommentResponse()
        {
        }

        public CommentResponse(
            ModelStateDictionary modelState
            )
            : base(modelState)
        {
        }

        public CommentResponse(
            Exception exception
            )
            : base(exception)
        {
        }

        public CommentResponse(
            CodeReviewApplication.Models.Comment comment,
            CodeReviewApplication.Models.CommentThread thread
            )
        {
            Comment = new Comment(comment, thread);
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class CommentsResponse : Response
    {
        [DataMember]
        public Comment[] Comments;
    
        public CommentsResponse()
        {
        }

        public CommentsResponse(
            ModelStateDictionary modelState
            )
            : base(modelState)
        {
        }

        public CommentsResponse(
            Exception exception
            )
            : base(exception)
        {
        }

        public CommentsResponse(
            IEnumerable<CodeReviewApplication.Models.Comment> comments,
            CodeReviewApplication.Models.CommentThread thread
            )
        {
            Comments = Comment.ToArray(comments, thread);
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class CommentThreadSummaryResponse : Response
    {
        [DataMember]
        [XmlElement]
        public CommentThreadSummary CommentThreadSummary;

        public CommentThreadSummaryResponse()
        {
        }

        public CommentThreadSummaryResponse(
            ModelStateDictionary modelState
            )
            : base(modelState)
        {
        }

        public CommentThreadSummaryResponse(
            Exception exception
            )
            : base(exception)
        {
        }

        public CommentThreadSummaryResponse(
            CodeReviewApplication.Models.CommentThread thread
            )
        {
            CommentThreadSummary = new CommentThreadSummary(thread);
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class CommentThreadSummariesResponse : Response
    {
        [DataMember]
        public CommentThreadSummary[] CommentThreadSummaries;
    
        public CommentThreadSummariesResponse()
        {
        }

        public CommentThreadSummariesResponse(
            ModelStateDictionary modelState
            )
            : base(modelState)
        {
        }

        public CommentThreadSummariesResponse(
            Exception exception
            )
            : base(exception)
        {
        }

        public CommentThreadSummariesResponse(
            IEnumerable<CodeReviewApplication.Models.CommentThread> threads
            )
        {
            CommentThreadSummaries = CommentThreadSummary.ToArray(threads);
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class CommentThreadResponse : Response
    {
        [DataMember]
        [XmlElement]
        public CommentThread CommentThread;
    
        public CommentThreadResponse()
        {
        }

        public CommentThreadResponse(
            ModelStateDictionary modelState
            )
            : base(modelState)
        {
        }

        public CommentThreadResponse(
            Exception exception
            )
            : base(exception)
        {
        }

        public CommentThreadResponse(
            CodeReviewApplication.Models.CommentThread thread
            )
        {
            CommentThread = new CommentThread(thread);
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class CommentThreadsResponse : Response
    {
        [DataMember]
        public CommentThread[] CommentThreads;

        public CommentThreadsResponse()
        {
        }

        public CommentThreadsResponse(
            ModelStateDictionary modelState
            )
            : base(modelState)
        {
        }

        public CommentThreadsResponse(
            Exception exception
            )
            : base(exception)
        {
        }

        public CommentThreadsResponse(
            IEnumerable<CodeReviewApplication.Models.CommentThread> threads
            )
        {
            CommentThreads = CommentThread.ToArray(threads);
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class ChangeResponse : Response
    {
        [DataMember]
        [XmlElement]
        public Change Change;

        public ChangeResponse()
        {
        }

        public ChangeResponse(
            ModelStateDictionary modelState
            )
            : base(modelState)
        {
        }

        public ChangeResponse(
            Exception exception
            )
            : base(exception)
        {
        }

        public ChangeResponse(ChangeListItem changeListItem)
        {
            Change = new Change(changeListItem);
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class ChangesResponse : Response
    {
        [DataMember]
        public Change[] Changes;

        public ChangesResponse()
        {
        }

        public ChangesResponse(
            ModelStateDictionary modelState
            )
            : base(modelState)
        {
        }

        public ChangesResponse(
            Exception exception
            )
            : base(exception)
        {
        }

        public ChangesResponse(
            IEnumerable<ChangeListItem> changeListItems
            )
        {
            Changes = Change.ToArray(changeListItems);
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class ChangeListSummaryResponse : Response
    {
        [DataMember]
        [XmlElement]
        public ChangeListSummary ChangeListSummary;

        public ChangeListSummaryResponse()
        {
        }

        public ChangeListSummaryResponse(
            ModelStateDictionary modelState
            )
            : base(modelState)
        {
        }

        public ChangeListSummaryResponse(
            Exception exception
            )
            : base(exception)
        {
        }

        public ChangeListSummaryResponse(
            CodeReviewApplication.Models.ChangeList changeList
            )
        {
            ChangeListSummary = new ChangeListSummary(changeList);
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class ChangeListSummariesResponse : Response
    {
        [DataMember]
        public ChangeListSummary[] ChangeListSummaries;

        public ChangeListSummariesResponse()
        {
        }

        public ChangeListSummariesResponse(
            ModelStateDictionary modelState
            )
            : base(modelState)
        {
        }

        public ChangeListSummariesResponse(
            Exception exception
            )
            : base(exception)
        {
        }

        public ChangeListSummariesResponse(
            IEnumerable<CodeReviewApplication.Models.ChangeList> changeLists
            )
        {
            ChangeListSummaries = ChangeListSummary.ToArray(changeLists);
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class ChangeListResponse : Response
    {
        [DataMember]
        [XmlElement]
        public ChangeList ChangeList;

        public ChangeListResponse()
        {
        }

        public ChangeListResponse(
            ModelStateDictionary modelState
            )
            : base(modelState)
        {
        }

        public ChangeListResponse(
            Exception exception
            )
            : base(exception)
        {
        }

        public ChangeListResponse(
            CodeReviewApplication.Models.ChangeList changeList
            )
        {
            ChangeList = new ChangeList(changeList);
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class ChangeListsResponse : Response
    {
        [DataMember]
        public ChangeList[] ChangeLists;

        public ChangeListsResponse()
        {
        }

        public ChangeListsResponse(
            ModelStateDictionary modelState
            )
            : base(modelState)
        {
        }

        public ChangeListsResponse(
            Exception exception
            )
            : base(exception)
        {
        }

        public ChangeListsResponse(
            IEnumerable<CodeReviewApplication.Models.ChangeList> changeLists
            )
        {
            ChangeLists = ChangeList.ToArray(changeLists);
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class ReviewSummaryResponse : Response
    {
        [DataMember]
        [XmlElement]
        public ReviewSummary ReviewSummary;

        public ReviewSummaryResponse()
        {
        }

        public ReviewSummaryResponse(
            ModelStateDictionary modelState
            )
            : base(modelState)
        {
        }

        public ReviewSummaryResponse(
            Exception exception
            )
            : base(exception)
        {
        }

        public ReviewSummaryResponse(
            ReviewView reviewView,
            string userId
            )
        {
            ReviewSummary = new ReviewSummary(reviewView.Review, userId);
        }

        public ReviewSummaryResponse(
            CodeReviewApplication.Models.Review review,
            string userId
            )
        {
            ReviewSummary = new ReviewSummary(review, userId);
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class ReviewSummariesResponse : Response
    {
        [DataMember]
        public ReviewSummary[] ReviewSummaries;

        public ReviewSummariesResponse()
        {
        }

        public ReviewSummariesResponse(
            ModelStateDictionary modelState
            )
            : base(modelState)
        {
        }
        
        public ReviewSummariesResponse(
            Exception exception
            )
            : base(exception)
        {
        }

        public ReviewSummariesResponse(
            IEnumerable<ReviewView> reviewViews,
            string userId
            )
        {
            ReviewSummaries = ReviewSummary.ToArray(reviewViews, userId);
        }

        public ReviewSummariesResponse(
            IEnumerable<CodeReviewApplication.Models.Review> reviews,
            string userId
            )
        {
            ReviewSummaries = ReviewSummary.ToArray(reviews, userId);
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class ReviewResponse : Response
    {
        [DataMember]
        [XmlElement]
        public Review Review;

        public ReviewResponse()
        {
        }

        public ReviewResponse(
            ModelStateDictionary modelState
            )
            : base(modelState)
        {
        }

        public ReviewResponse(
            Exception exception
            )
            : base(exception)
        {
        }

        public ReviewResponse(
            CodeReviewApplication.Models.Review review,
            string userId
            )
        {
            Review = new Review(review, userId);
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class ReviewsResponse : Response
    {
        [DataMember]
        public Review[] Reviews;

        public ReviewsResponse()
        {
        }

        public ReviewsResponse(
            ModelStateDictionary modelState
            )
            : base(modelState)
        {
        }

        public ReviewsResponse(
            Exception exception
            )
            : base(exception)
        {
        }

        public ReviewsResponse(
            IEnumerable<ReviewView> reviewViews,
            string userId
            )
        {
            Reviews = Review.ToArray(reviewViews, userId);
        }

        public ReviewsResponse(
            IEnumerable<CodeReviewApplication.Models.Review> reviews,
            string userId
            )
        {
            Reviews = Review.ToArray(reviews, userId);
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class DepotChangeListsResponse : Response
    {
        [DataMember]
        public DepotChangeList[] ChangeLists;

        public DepotChangeListsResponse()
        {
        }

        public DepotChangeListsResponse(
            ModelStateDictionary modelState
            )
            : base(modelState)
        {
        }

        public DepotChangeListsResponse(
            Exception exception
            )
            : base(exception)
        {
        }

        public DepotChangeListsResponse(
            IEnumerable<ChangeListDetails> changeLists
            )
        {
            ChangeLists = DepotChangeList.ToArray(changeLists);
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class ReviewChangeListPackagesResponse : Response
    {
        [DataMember(IsRequired = false)]
        [XmlElement]
        public ReviewChangeListPackage[] ChangeListPackages;

        public ReviewChangeListPackagesResponse()
        {
        }

        public ReviewChangeListPackagesResponse(
            ModelStateDictionary modelState
            )
            : base(modelState)
        {
        }

        public ReviewChangeListPackagesResponse(
            Exception exception
            )
            : base(exception)
        {
        }

        public ReviewChangeListPackagesResponse(
            Dictionary<string, string> uploadedFiles
            )
        {
            ChangeListPackages = (
                from uploadedFile in uploadedFiles
                select new ReviewChangeListPackage(uploadedFile.Key, uploadedFile.Value)
                ).ToArray();
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class DepotsResponse : Response
    {
        [DataMember(IsRequired = false)]
        [XmlElement]
        public Depot[] Depots;

        public DepotsResponse()
        {
        }

        public DepotsResponse(
            ModelStateDictionary modelState
            )
            : base(modelState)
        {
        }

        public DepotsResponse(
            Exception exception
            )
            : base(exception)
        {
        }

        public DepotsResponse(
            UserDepot depot
            )
        {
            List<UserDepot> depots = new List<UserDepot>();

            depots.Add(depot);

            Depots = Depot.ToArray(depots);
        }

        public DepotsResponse(
            IEnumerable<UserDepot> depots
            )
        {
            Depots = Depot.ToArray(depots);
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class RegistrationIdsResponse : Response
    {
        [DataMember(IsRequired = false)]
        [XmlElement]
        public Guid[] Ids;

        public RegistrationIdsResponse()
        {
        }

        public RegistrationIdsResponse(
            ModelStateDictionary modelState
            )
            : base(modelState)
        {
        }

        public RegistrationIdsResponse(
            Exception exception
            )
            : base(exception)
        {
        }

        public RegistrationIdsResponse(
            IEnumerable<Guid> requests
            )
        {
            Ids = requests.ToArray();
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class RegistrationResponse : Response
    {
        [DataMember(IsRequired = false)]
        [XmlElement]
        public Registration[] Registrations;

        public RegistrationResponse()
        {
        }

        public RegistrationResponse(
            ModelStateDictionary modelState
            )
            : base(modelState)
        {
        }

        public RegistrationResponse(
            Exception exception
            )
            : base(exception)
        {
        }

        public RegistrationResponse(
            RegistrationRequest registration
            )
        {
            List<RegistrationRequest> registrations = new List<RegistrationRequest>();

            registrations.Add(registration);

            Registrations = Registration.ToArray(registrations);
        }

        public RegistrationResponse(
            IEnumerable<RegistrationRequest> registrationRequests
            )
        {
            Registrations = Registration.ToArray(registrationRequests);
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class UserNotificationReponse : Response
    {
        public UserNotificationReponse()
        {
        }

        public UserNotificationReponse(
            ModelStateDictionary modelState
            )
            : base(modelState)
        {
        }

        public UserNotificationReponse(
            Exception exception
            )
            : base(exception)
        {
        }
    }

    [DataContract]
    [XmlRoot(Namespace = "urn:softactory.com/codereviewapplication/v1")]
    public partial class UserFeedbackResponse : Response
    {
        public UserFeedbackResponse()
        {
        }

        public UserFeedbackResponse(
            ModelStateDictionary modelState
            )
            : base(modelState)
        {
        }

        public UserFeedbackResponse(
            Exception exception
            )
            : base(exception)
        {
        }
    }

    #endregion

    public enum ResultTypeEnum
    {
        Html,
        Json,
        Xml
    }

    public class JsonHelper
    {
        private Type m_type;

        public JsonHelper(Type type)
        {
            m_type = type;
        }

        public string ToJson(object inputObject)
        {
            using (MemoryStream stream = new MemoryStream(4096))
            {            
                new DataContractJsonSerializer(m_type).WriteObject(stream, inputObject);

                return new UTF8Encoding(false).GetString(stream.ToArray());
            }
        }

        public object ToObject(Stream stream)
        {
            return new DataContractJsonSerializer(m_type).ReadObject(stream);
        }
    }
}
